package com.zrkizzy.thread.practice;

/**
 * 交替打印练习题
 * <p>
 *     编写一个Java程序，创建两个线程，一个线程打印奇数，另一个线程打印偶数，要求线程之间交替打印
 * </p>
 *
 * @author zhangrongkang
 * @since 2023/10/12
 */
public class PrintPractice {

    /**
     * 循环打印初始值
     */
    private static int COUNT = 1;

    /**
     * 对象锁，确保只有一个线程可以进入同步块
     */
    private static final Object LOCK = new Object();

    /**
     * 奇数类
     */
    static class OddPrinter implements Runnable {

        /**
         * 打印奇数
         */
        @Override
        public void run() {
            while (COUNT <= 100) {
                // 确保当前类中只有一个线程可以持有对象锁
                synchronized (LOCK) {
                    // 在加锁之后只有当前类可以进行打印，其余线程均进入等待状态
                    if ((COUNT & 1) == 1) {
                        // 如果当前为奇数
                        System.out.println("奇数： " + COUNT);
                        // 当前数 + 1
                        COUNT++;
                        // 唤醒等待打印偶数对线程
                        LOCK.notify();
                    } else {
                        // 如果不为奇数则让当前线程进入等待
                        try {
                            LOCK.wait();
                        } catch (InterruptedException e) {
                            // 中断
                            Thread.currentThread().interrupt();
                        }
                    }

                }
            }
        }
    }

    /**
     * 偶数类
     */
    static class EvenPrinter implements Runnable {

        /**
         * 打印偶数
         */
        @Override
        public void run() {
            while (COUNT <= 20) {
                // 获取对象锁
                synchronized (LOCK) {
                    // 如果当前为偶数
                    if ((COUNT & 1) != 1) {
                        System.out.println("偶数： " + COUNT);
                        COUNT++;
                        // 通知其他等待的线程释放锁
                        LOCK.notify();
                    } else {
                        // 当前线程进入等待
                        try {
                            // 等待过程中不会占用CPU资源
                            LOCK.wait();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        // 创建奇数线程和偶数线程
        Thread oddThread = new Thread(new OddPrinter());
        Thread evenThread = new Thread(new EvenPrinter());

        // 启动线程
        oddThread.start();
        evenThread.start();
    }
}
